package com.iocup.keybastion.sso.core;


import com.iocup.keybastion.common.AuthConstant;
import com.iocup.keybastion.context.WebContextHolder;
import com.iocup.keybastion.core.store.CacheStore;
import com.iocup.keybastion.exception.AuthenticationException;
import com.iocup.keybastion.sso.common.ChallengeDigestsUtils;
import com.iocup.keybastion.sso.common.RequestParam;
import com.iocup.keybastion.sso.common.SsoConstant;
import com.iocup.keybastion.sso.common.SsoUtils;
import com.iocup.keybastion.sso.config.SsoProperties;
import com.pine.sunflower.core.id.IDGenerator;
import com.pine.sunflower.core.utils.RandomUtil;

/**
 * @author xyjxust
 * @create 2022/3/24 9:29
 **/
public class DefaultSsoAuthFunction implements SsoAuthFunction {

    private SsoProperties ssoProperties;

    private CacheStore cacheStore;

    private static final String STATE_KEY = AuthConstant.CACHE_NAMESPACE + "STATE:";

    private static String[] digests = new String[]{"MD5", "SHA-1", "SHA-256", "SHA-512"};

    public DefaultSsoAuthFunction(SsoProperties ssoProperties, CacheStore cacheStore) {
        this.ssoProperties = ssoProperties;
        this.cacheStore = cacheStore;
    }

    @Override
    public void handle(WebContextHolder contextHolder) {
        if(!contextHolder.getRequestParameter(SsoConstant.redirect).isPresent()){
           throw new AuthenticationException("跳转地址不能为空");
        }
        //生成防重放攻击码
        String state = IDGenerator.UUID.generate();
        //生成密钥
        String verifier = IDGenerator.UUID.generate();
        //随机获取算法的索引
        int digestIndex = RandomUtil.getRandom().nextInt(digests.length);
        //随机获取算法的名字
        String challengeMethod = digests[digestIndex];
        try {
            //生成verifier加密后的数据
            String challenge = ChallengeDigestsUtils.digest(verifier, challengeMethod);
            RequestParam requestParam = new RequestParam();
            requestParam.setChallenge(challenge);
            requestParam.setState(state);
            requestParam.setVerifier(verifier);
            requestParam.setChallengeMethod(challengeMethod);
          //  requestParam.setRequestUrl(contextHolder.getFullRequestURL());
            requestParam.setRequestUrl(contextHolder.getRequestParameter(SsoConstant.redirect).get());
            //保存state-->RequestParam(原始url，算法，密码等)
            this.cacheStore.setValue(buildStateKey(state), requestParam, ssoProperties.getStateExpire());
            //跳转至sso认证服务器的认证接口
            contextHolder.responseRedirect(SsoUtils.buildAuthRedirectUrl(ssoProperties.getAuthUrl(),ssoProperties.getCallbackUrl(),
                    state, challengeMethod, challenge,ssoProperties.getClientId()
            ));
        } catch (Exception e) {
            throw new AuthenticationException(String.format("加载摘要算法错误,原因：%s", e.getMessage()));
        }
    }

    private String buildStateKey(String token) {
        return String.format("%s%s", STATE_KEY, token);
    }
}
